package fb4java.service;

import fb4java.Facebook4j;
import fb4java.beans.Link;
import fb4java.exception.FB4JavaException;
import fb4java.http.HttpResponseMessage;

import org.apache.http.client.ClientProtocolException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Map;

/**
 * 
 * fb4java<br />
 * fb4java.service
 * 
 * @author Choongsan Ro
 * @version 1.0 2010. 5. 5.
 */
public class AdministrativeService extends Service {

    /**
     * 
     * fb4java<br />
     * fb4java.service
     * 
     * @author Choongsan Ro
     * @version 1.0 2010. 5. 6.
     */
    public static enum IntegrationPointName {
	NotificationsPerDay("notifications_per_day"), AnnouncementNotificationPerWeek(
		"announcement_notifications_per_week"), RequestsPerDay("requests_per_day"), EmailsPerDay(
		"emails_per_day"), EmailDisableMessageLocation("email_disable_message_location");

	private String name;

	private IntegrationPointName(String n) {
	    name = n;
	}

	@Override
	public String toString() {
	    return name;
	}
    }

    private static final String ADMIN_BAN_USER = "admin.banUsers";
    private static final String ADMIN_GET_ALLOCATION = "admin.getAllocation";
    private static final String ADMIN_GET_APP_PROPERTIES = "admin.getAppProperties";
    private static final String ADMIN_GET_BANNED_USERS = "admin.getBannedUsers";
    private static final String ADMIN_GET_METRICS = "admin.getMetrics";
    private static final String ADMIN_GET_RESTRICTION_INFO = "admin.getRestrictionInfo";
    private static final String ADMIN_SET_APP_PROPERTIES = "admin.setAppProperties";
    private static final String ADMIN_SET_RESTRICTION_INFO = "admin.setRestrictionInfo";
    private static final String ADMIN_UNBAN_USERS = "admin.unbanUsers";
    private static final String APPLICATION_GET_PUBLICINFO = "application.getPublicInfo";
    private static final String BATCH_RUN = "batch.run";
    private static final String DATA_SET_COOKIE = "data.setCookie";
    private static final String LINKS_GET_STATS = "links.getStats";
    private static final String LIVEMESSAGE_SEND = "liveMessage.send";
    private static final String NOTIFICATIONS_MARK_READ = "notifications.markRead";
    private static final String NOTIFICATIONS_SEND_EMAIL = "notifications.sendEmail";

    public AdministrativeService(Facebook4j f4j) {
	super(f4j);
    }

    /**
     * 
     * @param notificationIds
     * @return
     * @throws ClientProtocolException
     * @throws URISyntaxException
     * @throws IOException
     */
    public boolean markNotificationsAsRead(long[] notificationIds) throws ClientProtocolException, URISyntaxException,
	    IOException {
	if (notificationIds == null || notificationIds.length <= 0) {
	    throw new IllegalArgumentException("Please check parameters.");
	}
	Map<String, String> listOfMethods = getBasicParams();

	listOfMethods.put(METHOD, NOTIFICATIONS_MARK_READ);

	StringBuffer nIds = new StringBuffer();

	for (long nid : notificationIds) {
	    nIds.append(nid);
	    nIds.append(',');
	}
	nIds.deleteCharAt(nIds.length() - 1);// delete last comma

	listOfMethods.put("notification_ids", nIds.toString());

	HttpResponseMessage response = f4j.sendGetRequest(listOfMethods);

	return response.getStatusCode() < 300;
    }

    /**
     * Returns information about one or more Facebook Share implementations. <br />
     * <br/>
     * Because of data caching reasons, you can make this API call only once
     * every 2 minutes for a given Share URL. <br/>
     * <br/>
     * 
     * @param urls
     *            A list of Facebook Share URLs for which you want to get
     *            data.URL must be encoded.
     * @return
     * @throws ClientProtocolException
     * @throws URISyntaxException
     * @throws IOException
     * @throws JSONException
     */
    public ArrayList<Link> getLinkStats(String[] urls) throws ClientProtocolException, URISyntaxException, IOException,
	    JSONException {
	Map<String, String> listOfMethods = getBasicParams();
	ArrayList<Link> rslt = new ArrayList<Link>();

	if (urls == null || urls.length < 0) {
	    throw new IllegalArgumentException("");
	}

	StringBuffer strUrls = new StringBuffer();

	for (String url : urls) {
	    strUrls.append(url);
	    strUrls.append(',');
	}
	strUrls.deleteCharAt(strUrls.length() - 1);// delete last comma

	listOfMethods.put("urls", "" + strUrls);

	listOfMethods.put(METHOD, LINKS_GET_STATS);

	HttpResponseMessage response = f4j.sendGetRequest(listOfMethods);

	JSONArray root = new JSONArray(response.getResponse());
	int numOfLinks = root.length();
	for (int a = 0; a < numOfLinks; a++) {
	    JSONObject aLink = root.getJSONObject(a);
	    rslt.add(new Link(aLink));
	}
	return rslt;
    }

    /**
     * 
     * @param properties
     * @return
     * @throws ClientProtocolException
     * @throws URISyntaxException
     * @throws IOException
     */
    public boolean setAppProperties(JSONObject properties) throws ClientProtocolException, URISyntaxException,
	    IOException {
	if (properties == null) {
	    throw new IllegalArgumentException("Please check parameters.");
	}
	Map<String, String> listOfMethods = getBasicParams();

	listOfMethods.put(METHOD, ADMIN_SET_APP_PROPERTIES);

	listOfMethods.put("notification_ids", properties.toString());

	HttpResponseMessage response = f4j.sendGetRequest(listOfMethods);

	return response.getStatusCode() < 300;
    }

    /**
     * 
     * @param ipn
     * @return
     * @throws ClientProtocolException
     * @throws URISyntaxException
     * @throws IOException
     * @throws FB4JavaException
     * @throws JSONException
     */
    public int adminGetAllocation(IntegrationPointName ipn) throws ClientProtocolException, URISyntaxException,
	    IOException, FB4JavaException, JSONException {

	if (ipn == null) {
	    throw new IllegalArgumentException("Please check parameters.");
	}

	Map<String, String> listOfMethods = getBasicParams();
	listOfMethods.put(METHOD, ADMIN_GET_ALLOCATION);
	listOfMethods.put("integration_point_name", ipn.toString());

	HttpResponseMessage response = f4j.sendGetRequest(listOfMethods);

	String respStr = response.getResponse();

	if (respStr == null || respStr.trim().equals("")) {
	    throw new FB4JavaException();
	}

	int rslt = 0;

	try {
	    rslt = Integer.parseInt(respStr);
	} catch (Exception e) {
	    JSONObject errorMsg = response.toJSONObject();
	    throw new FB4JavaException(errorMsg.getInt("error_code"), errorMsg.getString("error_msg"));
	}

	return rslt;
    }
}
